
/*
*Pool Public Licence version 0.1 or later
*Released on 20th April 2008.
*Any voilations can be repoted at paritosh@wikiocean.net
*What is treated as voilations can be found at www.wikiocean.net/ppl1-voilations* 
******************************************************************************
* The contents of this file are subject Affero GPL v3 and later with additional conditions.
* The additional conditions are to be considered as part of the Affero GPL v3 and later.
* The additional conditions will supersede the Affero GPLv3 and later in case of conflict.
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.gnu.org/licenses/agpl.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Initial Developer of the Original Code is Paritosh Pungaliya.
* created by Paritosh Pungaliya are Copyright (C) Paritosh Pungaliya; All Rights Reserved.
* Contributions are Copyright (C) 2001-2008 Paritosh Pungaliya.

* Objective of the additional terms (license) 
* 1) Is to extend the software freedom to freedom to work.
* 2) To ensure that knowledge is free from monopoly of agencie(s).
* 3) To avoid a situation where big corporates or investors can buy out free software groups and companies and then start milking the communities built around it.
* (this trend can be seen how the openness changes in companies that get Venture Capital funding.)
* (if you agree to this logic I invite you to our group to work together)

* Additional conditions
*  0) Source code will also include
* 	a) data dictionaries, data ontologies which are used to alter the behavior of code or to control           the features of application.
* 	b) Any code generated or derived automatically or manually from this code or logic
*  1) The revenue generated by deploying, implementing , selling services and other activities
*  	 based on this source code should be shared 100%, between the people working on it.
*  2) Capital invested should be given only fixed rate of return or linked to revenue/surplus growth for limited time.
*  3) People working on the project should always have an option to replace the capital provider in full or part with lower cost capital.
*  4) Their should not be any ownership which can be sold as a claim on future profit to be generated from the work of people working on the code.
*  5) Brand thus generated should belong to the group.
*  6) For old and new members revenue sharing should be equal for same work equivalent.
*  7) The share of revenue should be decided by bidding for work before allocation of work within the group.
*  8) Before bidding various method of measuring the work should be clearly defined and published in public domain. Any change in process should also be publised in public domain imediately.
*  9) All data related to to revenue sharing should be published as and when generated in public domain.
*  10) For group of people having size more than 10 people will have to make it open online for others to participate in bids. 
*  11) All people involved in related and sub project will be treated as a group.
*  12) Once this license is being used for a certain code then all and any other software services being provided by the group should complusorilly come under 100% revenue sharing.
*  13) Cross subsidization should not happen under this revenue share, no additional benefit should be drawn from the people, by the employing agency.
*  14) Any position or knowledge or legal structure created relating to people working on code, which adversely affects the spirit of 100% revenue share will be treated as a violation.
*  15) Revenue sharing defined.
*     a) includes direct revenue and also intangible gains like brand, and organization.
*     b) No personal judgment should be involved in judging the distribution of revenue.It has to be pre-defined formula based.
*     c)100% of revenue should be shared before expenses and recievers should have control over what expenses to incur.
*     d)For the work done in any month by contributing group member, working on any project can be given revenue share from the work done by the group, for a maximum of 18 months after that month.
*     e)Revenue should be apportioned to the month in which work is done and not when received.
*  The group fulfilling the above conditions also has to be a wiki ecosystem further defined in www.wekosystem.org or read about Wekosystem at www.wikiocean.net

*  ******************************************************************************
*/  
package event;

import integration.*;
import integration.join.Joinoperation;
import integration.join.Operation;


import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Map;
import java.util.Vector;

import control.RequestParameter;

import pool.bean.IdBean;
import pool.bean.Master_table_Bean;

import utility.CapitalChar;
import dbmanager.DBManager;
import dbmanager.GetIdName;

public class Integration implements Event 
{	
	boolean RESULT = false;
	String Product;
	String mastertype;
	String masterid;
	String userid;
	DBManager database;
	GetIdName gid;
	String Masterobject;
	String TYPE = "type";
	String PRODUCT="product";
	String TABLE="table";
	String INTEGRETE="integrate";
	String TABLELIST="tablelist";
	String Process="Process";
	String RELATION = "relation";
	String JOIN = "join";
	
	LinkedList< Object> productlist=new LinkedList<Object>();
	LinkedList< Object> objectList=new LinkedList<Object>();

	Hashtable< Object, Object> relationObject = new Hashtable<Object, Object>() ;
	
	public void SetData(String Product, String type, String masterid,
			String userid, String Process) 
	{
		this.Product = Product;
		this.mastertype = type;   /* type in nothing but table name */
		this.masterid = masterid;
		this.userid =userid;	
		this.Process = Process;/* value of process is -> add,mod,del,view*/
	}


	public boolean getResult() 
	{	
		return RESULT;
	}

	public void initializationData(DBManager database) 
	{
		this.database = database;
		gid = new GetIdName(database);
		PRODUCT = gid.getId(PRODUCT);
		TABLE = gid.getId(TABLE);
		INTEGRETE = gid.getId(INTEGRETE);
		TABLELIST =gid.getId(TABLELIST);
		RELATION = gid.getId(RELATION);
		TYPE = gid.getId(TYPE);
		JOIN = gid.getId(JOIN);
	}

	public void setObject(String Object) 
	{
		try 
		{
			Hashtable<Object, Object> poolHash = new Hashtable<Object, Object>();			
			if(Process.equalsIgnoreCase("add"))
			{
				ResultSet rs = null;
				String query = "select d3.pv  object from property_details d3 JOIN(property_details d JOIN property_details d2 on (d.mid=d2.mid))ON (d.mid=d3.mid)" +
				"where d.pid = "+TABLE+" and  d2.pid = "+TYPE+" and d2.pv= "+RELATION+" and d.pv= "+mastertype+" and d3.pid = "+TABLE;
				ResultSet resultset = database.getSelect(query);
				
				String objStr = "";
				Product = gid.getId(Product);
				while(resultset.next())
				{
					String object = resultset.getString("object").toString();
					
					String product = getProduct(object);
					if(!product.equalsIgnoreCase(Product))
					{
						if(!objectList.contains(object))
						{
							objectList.add(object);
							objStr = objStr + object + ",";
						}
					}
					else 
					{
						rs = database.getSelect("select p.pv joinobj, q.pv tableobj from property_details p JOIN property_details q ON(p.pv = q.mid) where p.mid="+object+" and p.pid = "+gid.getId("JOIN")+" and q.pid="+gid.getId("table"));
						while(rs.next())
						{
							String joinobj = rs .getString("joinobj");
							String tablobj = rs.getString("tableobj");
							poolHash.putAll(getPoolHash(joinobj,tablobj,masterid));
						}
						rs.close();
					}
				}
				resultset.close();
		
				Hashtable<Object, Object> fieldHash = new Hashtable<Object, Object>();
				boolean RelationFlag = false;
				for(int i=0;i<objectList.size();i++)
				{
					String integrationobj = objectList.get(i).toString();
					
					String parentMaster;
					//master = isertMaster(integrationobj,"", fieldHash,poolHash);
					parentMaster = insertObject(integrationobj,"", new Hashtable<Object, Object>(),poolHash);
					relationObject.put(gid.getItem(integrationobj), parentMaster);
					parentMaster = gid.getId(parentMaster);
					processQuery(integrationobj, parentMaster);
					
					
					resultset = database.getSelect("select p.pv joinobj, q.pv tableobj from property_details p JOIN property_details q ON(p.pv = q.mid) where p.mid="+integrationobj+" and p.pid = "+gid.getId("JOIN")+" and q.pid="+gid.getId("table"));
										
					while(resultset.next())
					{
						try 
						{
							String joinobj = resultset.getString("joinobj");
							String tablobj = resultset.getString("tableobj");
							fieldHash.putAll(checkJoin(parentMaster,joinobj));
							//master = isertMaster(tablobj,"",new Hashtable<Object, Object>(),poolHash);
							
							String master = insertObject(tablobj,"",fieldHash,poolHash);
							//Call to checkJoin and pass joinobject and name of the master
							relationObject.put(gid.getItem(tablobj), master);
							master = gid.getId(master);
							processQuery(tablobj, master);
							//fieldHash.putAll(checkJoin(master,joinobj));
						}
						catch (Exception e) {
							e.printStackTrace();
						}
					}
					resultset.close();
					/*master = isertMaster(integrationobj,"", fieldHash,poolHash);
					relationObject.put(gid.getItem(integrationobj), master);
					master = gid.getId(master);
					processQuery(integrationobj, master);*/
					RelationFlag  = true;
				}
				if(RelationFlag)
				{
					relationObject.put(gid.getItem(mastertype), gid.getItem(masterid));
					Vector<Object> propertyVect = new Vector<Object>();
					/** It will insert into M & PL of the POOLDB. **/
					Enumeration<Object> keys = relationObject.keys();
					while(keys.hasMoreElements())
					{
						String key = keys.nextElement().toString();
						String value = relationObject.get(key).toString();
						Hashtable<Object, Object> hash = new Hashtable<Object, Object>();
						hash.put("pid", key);
						hash.put("pv", value);
						propertyVect.add(hash);
					}
					
					Hashtable<Object, Object> hash = new Hashtable<Object, Object>();
					hash.put("pid", "type");
					hash.put("pv", "tableRelation");
					propertyVect.add(hash);
				
					IdBean idObj = new IdBean(database);
					idObj.setTable("master_table");
					idObj.execute();
					String id = idObj.getId();
					
					
					RequestParameter rqp = new RequestParameter();
					rqp.setUsername("+911234567891");
					rqp.setPassword("891");
					rqp.setProcess("add");
					rqp.setVersion("11");
					rqp.setMessage("");
					rqp.setRequest("master_table");
					
					String master1 = "tableRelation_" + id;
					Master_table_Bean mtb = new Master_table_Bean();
					mtb.setDBManager(database);
					mtb.setReqParam(rqp);
					mtb.setNewMasterObject(master1);
		//				getPropertyVector();
					mtb.setPropertyVector(propertyVect);
					mtb.insert();
				}
				
			}
			else if(Process.equalsIgnoreCase("mod"))
			{
				Hashtable<Object, Object> fieldHash = new Hashtable<Object, Object>();
				Hashtable<Object, Object> relationObjectHash = new Hashtable<Object, Object>();
				relationObjectHash.putAll(getRelationObjectHash(masterid));
				if(!Product.equalsIgnoreCase("pool"))
					relationObjectHash.putAll(removeSameProduct(relationObjectHash));
				
				Enumeration< Object> enumerator = relationObjectHash.keys();
				while(enumerator.hasMoreElements())
				{
					String integrationobj = enumerator.nextElement().toString();
					
					String master;
					master = relationObjectHash.get(integrationobj).toString();
					master = insertObject(integrationobj, master,fieldHash,poolHash);
					master = gid.getId(master);
					processQuery(integrationobj, master);
				}
			}
			else if(Process.equalsIgnoreCase("del"))
			{
				String query = "select d3.pv  object from property_details d3 JOIN(property_details d JOIN property_details d2 on (d.mid=d2.mid))ON (d.mid=d3.mid)" +
				"where d.pid = "+TABLE+" and  d2.pid = "+TYPE+" and d2.pv= "+RELATION+" and d.pv= "+mastertype+" and d3.pid = "+TABLE;
				ResultSet resultset = database.getSelect(query);
				
				//Product = gid.getId(Product);
				while(resultset.next())
				{
					String object = resultset.getString("object").toString();
					
					String product = getProduct(object);
					if(!product.equalsIgnoreCase(Product))
					{
						if(!objectList.contains(object))
						{
							objectList.add(object);
						}
					}
				}
				resultset.close();
				
				Hashtable<Object, Object> fieldHash = new Hashtable<Object, Object>();
				Hashtable<Object, Object> relationObjectHash = new Hashtable<Object, Object>();
				relationObjectHash.putAll(getRelationObjectHash(masterid));
				if(!Product.equalsIgnoreCase("pool"))
					relationObjectHash.putAll(removeSameProduct(relationObjectHash));
				
				Enumeration< Object> enumerator = relationObjectHash.keys();
				if(objectList.contains(mastertype))
				{
					while(enumerator.hasMoreElements())
					{
						String integrationobj = enumerator.nextElement().toString();
						
						String master;
						master = relationObjectHash.get(integrationobj).toString();
						//master = isertMaster(integrationobj, master,fieldHash,poolHash);
						//master = gid.getId(master);
						processQuery(integrationobj, master);
					}	
				}
				else
				{
					while(enumerator.hasMoreElements())
					{
						String integrationobj = enumerator.nextElement().toString();
						
						String master;
						master = relationObjectHash.get(integrationobj).toString();
						Process = "del";
						//master = isertMaster(integrationobj, master,fieldHash,poolHash);
						//master = gid.getId(master);
						Process = "mod";
						processQuery(integrationobj, master);
					}
				}
			}
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
		RESULT = true;
	}
	
	private Map<? extends Object, ? extends Object> removeSameProduct(Hashtable<Object, Object> relationObjectHash) 
	{
		String query = "Select d3.pv from property_details d3 JOIN(property_details d JOIN property_details d2 ON (d.mid=d2.mid)) ON (d2.mid = d3.mid) " +
		" where d.pid = "+TABLE+" and  d2.pid = "+TYPE+" and d2.pv= "+TABLELIST+" and d.pv = "+mastertype+" and d3.pid = "+TABLE;
		ResultSet resultset = database.getSelect(query);
		
		try 
		{
			while(resultset.next())
			{
				String tabletype = resultset.getString("pv");
				if(relationObjectHash.containsKey(tabletype)||relationObjectHash.containsKey(TYPE))
					relationObjectHash.remove(tabletype);
			}
			if(relationObjectHash.containsKey(TYPE))
				relationObjectHash.remove(TYPE);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return relationObjectHash;
	}


	private Hashtable<Object,Object> getRelationObjectHash(String masterid) 
	{
		Hashtable<Object,Object> hash = new Hashtable<Object, Object>();
		String TABLERELATION = "tableRelation";
		TABLERELATION = gid.getId(TABLERELATION );
		String query = "SELECT d2.pid,d2.pv from property_details d2 JOIN( property_details d JOIN property_details d1 ON (d.mid=d1.mid))ON(d2.mid=d1.mid) ";
		query = query + " where d.pid = " + TYPE + " AND d.pv = " + TABLERELATION + " AND d1.pv = " + masterid;
				
		ResultSet rs = database.getSelect(query);
		try 
		{
			while(rs.next())
			{
				hash.put(rs.getString("pid"), rs.getString("pv"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return hash;
	}


	/** It will returns the parent object of the given object.*/
	public String getParent(String object) 
	{
		/*select d3.mid  object from property_details d3 JOIN (property_details d JOIN property_details d2 on
		(d.mid=d2.mid))ON (d.mid=d3.pv) where d.pid = 9 and d.pv = 8449 and d2.pid = 2223 and d2.pv = 8405*/
		//String joinID = gid.getId(JOIN); 
		String query = "SELECT d3.mid parent from property_details d3 JOIN (property_details d JOIN property_details d2 ";
		query = query + "ON (d.mid=d2.mid)) ON (d.mid=d3.pv) WHERE p.pid = " + TYPE + " AND d.pv = " + JOIN + " AND d2.pid = " + TABLE + " AND d2.pv = " + object;
		
		ResultSet rsParent = database.getSelect(query);
		try 
		{
			rsParent.next();
			return rsParent.getString("mid");
		} catch (Exception e) {
			System.out.println(" Parent Not Found....");
			e.printStackTrace();
		}
		return null;		
	}
	
	public String getObjectList(String object) 
	{
		String joinID = gid.getId(JOIN); 
		String query = "SELECT d3.mid parent from property_details d3 JOIN (property_details d JOIN property_details d2 ";
		query = query + "ON (d.mid=d2.mid)) ON (d.mid=d3.pv) WHERE p.pid = " + TYPE + " AND d.pv = " + joinID + " AND d2.pid = " + TABLE + " AND d2.pv = " + object;
		query = query + "";
		
		return null;				
	}
	
	String insertObject(String tableobj,String masterObj,Hashtable<Object, Object> fieldHash,Hashtable<Object, Object> poolHash2)
	{
		integration.join.Operation operation;
		try
		{
			Class c = Class.forName("integration.join."+CapitalChar.makeFirstCharCapital(Process));
			operation = (integration.join.Operation) c.newInstance();
			
			operation.setDatabase(database);
			operation.setTableObj(tableobj);
			operation.setRecentTableObject(masterid);
			operation.setPoolHash(poolHash2);
			operation.generateProperty();
			operation.setFields(fieldHash);
			operation.getPropertyVector();
			operation.setMaster(masterObj);
			return operation.performOperation();
		} 
		catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (Exception e) {
		}
		return null;
	}
	
	void processQuery(String type, String master)
	{
		
		integration.pushdata.Operation operation;
		try 
		{
			Class c = Class.forName("integration.pushdata."+CapitalChar.makeFirstCharCapital(Process));
			operation = (integration.pushdata.Operation) c.newInstance();
			operation.setDatabase(database);
			operation.setRecentTableObject(master);
			operation.setTableObj(type);
			operation.performOperation();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		
		/*
		QueryProcessor qrypro = new QueryProcessor();
		qrypro.setDatabase(database);
		qrypro.setRecentTableObject(master);
		qrypro.setTableObj(type);
		qrypro.generateQuery();
		qrypro.insertQuery();
		*/
	}
	
	private Hashtable<Object, Object> getPoolHash(String joinobj, String tablobj, String masterid2) 
	{
		String LHS = gid.getId("LHS");     // treated as inside Outside Object
		String RHS = gid.getId("RHS");		// treated as inside Inside Object
		String fieldname=null;
		String key = null;
		String id = null;
		ResultSet rsPoolValue = database.getSelect("SELECT mid, pid, pv, vt FROM property_details  WHERE mid = " + joinobj + " and pid in("+LHS+","+RHS+")");
		try 
		{
			while(rsPoolValue.next())
			{
				if(rsPoolValue.getString("pid").equalsIgnoreCase(LHS))
				{
					key = rsPoolValue.getString("pv");
				}
				else if(rsPoolValue.getString("pid").equalsIgnoreCase(RHS))
				{
					fieldname = rsPoolValue.getString("pv");
				}
			}
			rsPoolValue.close();
			rsPoolValue = database.getSelect("SELECT mid, pid, pv, vt FROM property_details  WHERE mid = " + masterid2 + " and pid ="+key);
			rsPoolValue.next();
			// get the object from the property_details where id = id_var and type = tableobj then call to insert master and generatePoolHash() function
			
			if(rsPoolValue.getString("pid").equals(key));
			{
				id = rsPoolValue.getString("pv");
				if(id.equalsIgnoreCase("0"))
				{
					id = rsPoolValue.getString("vt");
					rsPoolValue.close();
					rsPoolValue = database.getSelect("SELECT p.mid, p.pid, p.pv, p.vt FROM property_details p JOIN property_details p1 ON(p.mid = p1.mid)  WHERE p.pid = " + fieldname + " and p.vt ="+id + " and p1.pid ="+TYPE+" and p1.pv="+tablobj);
				}
				else
				{
					rsPoolValue.close();
					rsPoolValue = database.getSelect("SELECT p.mid, p.pid, p.pv, p.vt FROM property_details p JOIN property_details p1 ON(p.mid = p1.mid)  WHERE p.pid = " + fieldname + " and p.pv ="+id + " and p1.pid ="+TYPE+" and p1.pv="+tablobj);
				}
				rsPoolValue.next();
				String mid = rsPoolValue.getString("mid");
				
				relationObject.put(gid.getItem(tablobj), gid.getItem(mid));
				
				try 
				{
					Class c = Class.forName("integration.join."+CapitalChar.makeFirstCharCapital(Process));
					Operation operation = (Operation) c.newInstance();
					
					operation.setDatabase(database);
					operation.setTableObj(tablobj);
					operation.setRecentTableObject(mid);
					return operation.getPoolHash();
				}
				catch (ClassNotFoundException e) {
					e.printStackTrace();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			
		} 
		catch (SQLException e) {
		}
		return new Hashtable<Object, Object>();
	}
	private Hashtable<Object, Object> checkJoin(String master, String joinobj)
	{
		Hashtable<Object, Object> fieldHash = new Hashtable<Object, Object>();
		String LHS = gid.getId("LHS"); 		// treated as inside Outside Object
		String RHS = gid.getId("RHS");		// treated as inside Inside Object
		String fieldname=null;
		String key = null;
		
		ResultSet rsPoolValue = database.getSelect("SELECT mid, pid, pv, vt FROM property_details  WHERE mid = " + joinobj + " and pid in("+LHS+","+RHS+")");
		
		try 
		{
			while(rsPoolValue.next())
			{
				if(rsPoolValue.getString("pid").equalsIgnoreCase(LHS))
				{
					//fieldname = gid.getItem(rsPoolValue.getString("pv"));
					fieldname = rsPoolValue.getString("pv");
				}
				else if(rsPoolValue.getString("pid").equalsIgnoreCase(RHS))
				{
					key = rsPoolValue.getString("pv");
				}
			}
			rsPoolValue.close();
			rsPoolValue = database.getSelect("SELECT mid, pid, pv, vt FROM property_details  WHERE mid = " + master + " and pid ="+fieldname);
			rsPoolValue.next();
			fieldname = rsPoolValue.getString("pv");
			if(fieldname.equals("0"))
				fieldname = rsPoolValue.getString("vt");
			else
				fieldname = gid.getItem(fieldname);
			fieldHash.put(gid.getItem(key),fieldname);
		} 
		catch (SQLException e) {
		}
		return fieldHash;
	}
	private String getProduct(String object) 
	{
		try 
		{
			ResultSet rs = database.getSelect("select d3.mid product from property_details d3 JOIN(property_details d JOIN property_details d2 on (d.mid=d2.mid))ON (d.mid=d3.pv)" +
					"where d.pid = "+TABLE+" and d.pv= "+object+" and  d2.pid = "+TYPE+" and d2.pv= "+TABLELIST+" and d3.pid = "+TABLELIST);
			rs.next();
			object = rs.getString("product");
			rs.close();
		} 
		catch (SQLException e) {
			e.printStackTrace();
		}
		return object;
	}
	public static void main(String[] args) {
		Integration integ = new Integration();
		DBManager db = new DBManager();
		db.getConnect();
		integ.initializationData(db);
		integ.SetData("SugarpoolObject", "8413", "8509", "+911234567891", "add");
		System.out.println(integ.getPoolHash("8451", "8437","8509"));
	}
}
